package flexo.gui;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import flexo.common.LogMsgType;
import flexo.common.System;
import flexo.input.Event;
import flexo.input.InputSystem;

public class GuiSystem extends System implements flexo.input.EventListener
{	
	public static final String GUI_ACTIVATE = "gui_activate";
	public static final String ID = "gui";
	
	protected LinkedList<GuiListener> listeners;
	
	protected float sensitivity;
	protected List<Layout> layoutList;
	protected ThemePool themeList;
	protected String defaultTheme;
	
	protected Layout activeLayout = null;

	public GuiSystem()
	{
		super(ID, flexo.common.System.UPDATE_HALF);
		sensitivity = 1;
		
		layoutList = new LinkedList<Layout>();
		themeList = new ThemePool();
		defaultTheme = "flat";
		InputSystem input = (InputSystem)flexo.Kernel.getSystem(InputSystem.ID);
		input.addEventListener(this);
		
		listeners = new LinkedList<GuiListener>();
	}
	
	@Override
	public void remove()
	{
		super.remove();
		InputSystem input = (InputSystem)flexo.Kernel.getSystem(InputSystem.ID);
		input.removeEventListener(this);
	}
	
	public void setDefaultTheme(String themeName)
	{
		if (themeList.get(themeName) != null)
		{
			this.defaultTheme = themeName;
		}
		else
		{
			flexo.Kernel.log("flexo.gui.GuiSystem", "'"+themeName+"' can't be set as default theme (it's not registered)", LogMsgType.ERROR);
		}
	}
	
	public void addTheme(Theme theme)
	{
		if (themeList.get(theme.getName()) == null)
		{
			themeList.add(theme.getName(),theme);
		}
		else
		{
			flexo.Kernel.log("flexo.gui.GuiSystem", "'"+name+"' can't be added (another theme has that name already)", LogMsgType.WARNING);
		}
	}
	
	public void addLayout(int layer, String layoutFile)
	{
		flexo.Kernel.log("flexo.gui.GuiSystem", "Adding Layout '"+layoutFile+"'");
		Layout l = new Layout(layer,layoutFile,themeList.get(defaultTheme));
		layoutList.add(l);
		setActiveLayout(layer);
		l.setCursorSensitivity(sensitivity);
	}
	
	public void setActiveLayout(int layer)
	{
		flexo.Kernel.log("flexo.gui.GuiSystem", "Activating layout in layer " + layer, LogMsgType.DEBUG);
		
		// Disable the previous active layout
		if (activeLayout != null)
		{
			activeLayout.setCursorEnabled(false);
		}
		
		activeLayout = null;
		for (Layout l : layoutList)
		{
			if (l.getLayer() == layer)
			{
				activeLayout = l;
			}
		}
		
		// Enable the current active layout
		if (activeLayout != null)
		{
			activeLayout.setCursorEnabled(true);
		}
	}
	
	public void removeLayout(int layer)
	{
		flexo.Kernel.log("flexo.gui.GuiSystem", "Removing layout on layer " + layer);
		
		Iterator<Layout> iter = layoutList.iterator();
		while (iter.hasNext())
		{
			Layout l = iter.next();
			if (l.getLayer() == layer)
			{
				iter.remove();
			}
		}
		
		// If the deleted layer is active,
		// it sets the first available layer as the active one
		if (activeLayout.getLayer() == layer)
		{
			activeLayout = null;
			if (layoutList.size() > 0)
			{
				setActiveLayout(layoutList.get(0).getLayer());
			}
		}
	}
	
	public void setCursorSensitivity(float value)
	{		
		if (sensitivity > 0)
		{
			flexo.Kernel.log("flexo.gui.GuiSystem", "Setting cursor sensitivity to " + value, LogMsgType.DEBUG);
			
			this.sensitivity = value;
			
			for (Layout l : layoutList)
			{
				l.setCursorSensitivity(this.sensitivity);
			}
		}			
	}
	
	public void update()
	{
		if (activeLayout != null)
		{
			activeLayout.update();
		}
	}
	
	public void addGuiListener(GuiListener listener)
	{
		if (!listeners.contains(listener))
		{
			listeners.add(listener);
		}
	}
	
	public void removeGuiListener(GuiListener listener)
	{
		listeners.remove(listener);
	}

	@Override
	public void processEvent(Event e)
	{
		if (e.check(flexo.gui.GuiSystem.GUI_ACTIVATE) && e.getValue() >= 1)
		{
			if (this.activeLayout.event())
			{
				int layer = activeLayout.getLayer();
				String name = activeLayout.getActiveWidget();
				
				for (GuiListener l: listeners)
				{
					l.actionPerformed(layer, name);
				}
			}
		}
	}	
}
